// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <pollux/core/simple_function_metadata.h>
#include <pollux/expression/simple_function_registry.h>
#include <pollux/expression/vector_function.h>
#include <iostream>

namespace kumo::pollux {
    // This is a temp wrapper that defines udf<X> for a complete UDF.
    // We can remove this once macro-based udfs are completely deprecated.

    template<typename T>
    struct TempWrapper {
        template<typename B>
        using udf = T;
    };

    template<template <class...> typename T, typename... TArgs>
    using ParameterBinder = TempWrapper<T<exec::VectorExec, TArgs...> >;

    // Register a UDF with the given aliases. If an alias already
    // exists and 'overwrite' is true, the existing entry in the function
    // registry is overwritten by the current UDF. If an alias already exists and
    // 'overwrite' is false, the current UDF is not registered with this alias.
    // This method returns true if all 'aliases' are registered successfully. It
    // returns false if any alias in 'aliases' already exists in the registry and
    // is not overwritten.
    template<typename Func, typename TReturn, typename... TArgs>
    bool register_function(const std::vector<std::string> &aliases = {},bool overwrite = true) {
        using funcClass = typename Func::template udf<exec::VectorExec>;
        using holderClass = core::UDFHolder<
            funcClass,
            exec::VectorExec,
            TReturn,
            ConstantChecker<TArgs...>,
            typename UnwrapConstantType<TArgs>::type...>;
        return exec::register_simple_function<holderClass>(aliases, {}, overwrite);
    }

    // New registration function; mostly a copy from the function above, but taking
    // the inner "udf" struct directly, instead of the wrapper. We can keep both for
    // a while to maintain backwards compatibility, but the idea is to remove the
    // one above eventually.
    template<template <class> typename Func, typename TReturn, typename... TArgs>
    bool register_function(const std::vector<std::string> &aliases = {},
                          const std::vector<exec::SignatureVariable> &constraints = {}, bool overwrite = true) {
        using funcClass = Func<exec::VectorExec>;
        using holderClass = core::UDFHolder<
            funcClass,
            exec::VectorExec,
            TReturn,
            ConstantChecker<TArgs...>,
            typename UnwrapConstantType<TArgs>::type...>;
        return exec::register_simple_function<holderClass>(
            aliases, constraints, overwrite);
    }
} // namespace kumo::pollux
